// 属性提取 
// 当前运动函数只能水平方向移动 
// ele      运动的元素
// params   对象参数(接收运动的属性及其终点至 cssKey end,且可以接受多个)
// callback 每次运动完毕执行的回调函数 (把函数当成参数,传入到另一个函数中,让它在另一个函数中执行 => )


// 问题:
// 多元素同时运动式,启动下一个animate() 默认会暂停上一个运动的元素!!!!!!   => 最终只能跑一个

// 解决方案:
// 多元素同时运动时, 有几个元素就要有几个计时器  => 每个运动的元素都要有自己的计时器(而不是公用一个)

//animate(ball, { left: "1000px", top: 600 ,opacity:0.5});
function animate(ele, params, callback) { // params = {cssKey:end}

    // cur  1. 记录小球初始位置  2. 记录小球每次运动后的位置(以前存一个)
    // var cur = parseFloat(getStyle(ele, cssKey)); 
    // end = parseFloat(end);  // 如果有单位 => 去单位

    // debugger;
    var cur = {};  // 局部变量 => 对象,存储每一个运动的属性对应的当前值 => cur ={left:0,top:0,opacity:0}
    var end = {};  // 局部变量 => 对象,存储每一个运动的属性对应的终点值
    var speed = {}

    for (var cssKey in params) {  // 遍历传入的对象 cssKey键名 => 运动的属性名
        var curItem = parseFloat(getStyle(ele, cssKey))
        cur[cssKey] = curItem;

        var endItem = parseFloat(params[cssKey]);
        end[cssKey] = endItem;

        if (cssKey == "opacity") {  // 对于opacity来说 0-1  太小了, 一次就跑完了(没有运动效果), 而且opacity不需要带单位
            cur[cssKey] *= 1000;   // 起点值扩大1000倍
            end[cssKey] *= 1000;
        }

        speed[cssKey] = end[cssKey] > cur[cssKey] ? 30 : -30

    }
    // console.log(cur, end, speed);

    // 多元素同时运动时, 有几个元素就要有几个计时器  => 每个运动的元素都要有自己的计时器(而不是公用一个)
    // 可以尝试把计时器的编号存储到元素中  => 怎么存?

    // var obj = {};
    // obj.a = 100;  // 给对象新增属性

    // 元素节点 => html元素 也是一个特殊的对象 (官方内置属性 + 用户自定义属性)
    // ele.a = 100;   // 此属性属于用户自定义(对象中新增属性), 和官方内置属性没有关系

    // 把计时器的编号存储到元素上  => 对应元素的timer属性存储和清除计时器
    clearInterval(ele.timer);
    ele.timer = setInterval(function () {

        var flag = true; // 假设全都到达终点
        for (var cssKey in params) {
            cur[cssKey] += speed[cssKey];

            if (cssKey == "opacity") {
                ele.style[cssKey] = cur[cssKey] / 1000;  // 每次运动完毕缩小相应的倍数 opacity 赋值时不需要带单位  
            } else {
                ele.style[cssKey] = cur[cssKey] + "px";
            }

            // 判断是否到达终点 => 停下了
            // 理想情况下: cur == end  刚好到达终点  (但是如果需要运动的距离(终点-起点),不是speed的倍数 => 无法满足此条件)   => 无法停止

            // 解决方案:
            // 1. cur >= end    超出end或刚好到达终点,停下了(大于最大值)  => 强制到达终点  (此方案只适用于  end > start)
            // 2. Math.abs(cur - end) < Math.abs(speed)  => 在跑一次肯定超出,没有必要跑 => 直接到达终点

            if (Math.abs(cur[cssKey] - end[cssKey]) <= Math.abs(speed[cssKey])) { // 到达终点的条件

                // 强制到达终点  把cur的至更新为end值   !!!!!!
                cur[cssKey] = end[cssKey];

                if (cssKey == "opacity") {
                    ele.style[cssKey] = end[cssKey] / 1000;  // opacity 赋值时不需要带单位
                } else {
                    ele.style[cssKey] = end[cssKey] + "px";
                }
            } else {  // 没有到达终点
                flag = false;  // 
            }
        }
        if (flag) {
            clearInterval(ele.timer);
            ele.timer = null;

            if (callback && typeof callback == "function") {  // 判断是否传入回调函数
                callback();  // 存在就调用
            }
        }
    }, 5);
}

function getStyle(ele, cssKey) {
    if (window.getComputedStyle) {
        return window.getComputedStyle(ele)[cssKey];
    } else {
        return ele.currentStyle[cssKey];
    }
}